/**
 * 一个简单的Map实现
 */
export default class UglyMap {
  constructor() {
    const self = this

    const foreachMap = function(action) {
      const array = []
      const _map = self.map
      for (let i = 0, len = _map.length; i < len; i++) {
        array.push(action(_map[i]))
      }
      return array
    }

    const getValue = function(k) {
      // console.log('get', k)
      if (k !== undefined && k !== null) {
        const _map = self.map
        for (let i = 0, len = _map.length; i < len; i++) {
          if (_map[i].key === k) {
            return [i, _map[i].value]
          }
        }
      }
      return [-1, null]
    }

    this.map = []

    /**
     * 返回大小
     * @returns
     */
    this.size = function() {
      return self.map.length
    }

    /**
     * 判断是否为空
     * @returns
     */
    this.isEmpty = function() {
      return self.size() === 0
    }

    /**
     * 判断是否包含键
     * @param {*} k
     * @returns
     */
    this.containsKey = function(k) {
      const found = getValue(k)
      return found[0] !== -1
    }

    /**
     * 返回键的集合
     * @returns
     */
    this.keys = function() {
      return foreachMap((entry) => entry.key)
    }

    /**
     * 返回值的集合
     * @returns
     */
    this.values = function() {
      return foreachMap((entry) => entry.value)
    }

    /**
     * 返回项的集合
     * @returns
     */
    this.entries = function() {
      return foreachMap((entry) => entry)
    }

    /**
     * 设置键值对
     * @param {*} k
     * @param {*} v
     * @returns
     */
    this.put = function(k, v) {
      // console.log('put', k, v)
      const found = getValue(k)
      const _map = self.map
      if (found[0] === -1) {
        _map.push({
          key: k,
          value: v
        })
        return v
      }
      const oldVal = found[1]
      _map[found[0]].value = v
      return oldVal
    }

    /**
     * 获取键的值
     * @param {*} k
     * @returns
     */
    this.get = function(k) {
      const found = getValue(k)
      return found[1]
    }

    /**
     * 删除键
     * @param {*} k
     * @returns
     */
    this.remove = function(k) {
      // console.log('remove', k)
      if (k !== undefined && k !== null) {
        const _map = self.map
        for (let i = 0, len = _map.length; i < len; i++) {
          if (_map[i].key === k) {
            _map.splice(i, 1)
            return true
          }
        }
      }
      return false
    }

    /**
     * 清空集合
     */
    this.clear = function() {
      self.map.length = 0
    }

    /**
     * 遍历集合
     * @param {*} action
     * @returns
     */
    this.forEach = function(action) {
      if (action === undefined || action === null || !(action instanceof Function)) {
        return
      }
      const _map = self.map
      for (let i = 0, len = _map.length; i < len; i++) {
        action(_map[i])
      }
    }

    /**
     * 如果没有键，则设置键的值；返回键的值。
     * @param {*} k
     * @param {*} v
     * @returns
     */
    this.putIfAbsent = function(k, v) {
      const found = getValue(k)
      const _map = self.map
      if (found[0] === -1) {
        _map.push({
          key: k,
          value: v
        })
        return v
      }

      return found[1]
    }

    /**
     * 如果没有键，则计算并设置键的值；返回键的值。
     * @param {*} k
     * @param {*} action
     * @returns
     */
    this.computeIfAbsent = function(k, action) {
      if (action === undefined || action === null || !(action instanceof Function)) {
        return null
      }
      const found = getValue(k)
      const _map = self.map
      if (found[0] === -1) {
        const v = action(k)
        _map.push({
          key: k,
          value: v
        })
        return v
      }

      return found[1]
    }

    /**
     * 如果存在键，则计算值。
     * @param {*} k
     * @param {*} action
     * @returns
     */
    this.computeIfPresent = function(k, action) {
      if (action === undefined || action === null || !(action instanceof Function)) {
        return null
      }
      const found = getValue(k)
      const _map = self.map
      if (found[0] !== -1) {
        const v = action(k, found[1])
        _map[found[0]].value = v
        return v
      }

      return null
    }
  }
}
